`timescale 1ns / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:
//
// Create Date:   19:16:03 03/13/2024
// Design Name:   pipeline_CPU
// Module Name:   D:/ISE_Projects/CPU_emailbiju/pipeline_cpu_tb.v
// Project Name:  CPU_emailbiju
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: pipeline_CPU
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
////////////////////////////////////////////////////////////////////////////////

module pipeline_cpu_tb_i();
    reg clk, reset; 

	reg [31:0] idata;
	wire [31:0] DMEM_drdata_out;

    wire [31:0] iaddr;
    wire [31:0] x31;
	 wire [31:0] EM_daddr_out;
	 wire [31:0] MW_drdata_out;
	 wire [31:0] L_regdata_out;

	wire [31:0] dwdata;
	wire [3:0] we;

    pipeline_CPU dut(
        .clk(clk),
        .reset(reset),
		.idata(idata),
        .iaddr(iaddr),
		.DMEM_drdata_out(DMEM_drdata_out),

        .x31(x31),
		  .EM_daddr_out(EM_daddr_out),
		  .MW_drdata_out(MW_drdata_out),
		  .L_regdata_out(L_regdata_out),

		  .EM_dwdata_out(dwdata),
		  .EM_we_out(we)
    );
	 
    always #5 clk = ~clk;


	//8位imem
	reg [7:0] i_arr[0:1024*256-1];
	initial begin
		$readmemh("dhrystone/dhry.hex",i_arr);	//firmware/firmware.hex   dhrystone/dhry.hex
	end
	always @(negedge clk) //posedge clk
    begin
        idata[7:0] <= i_arr[iaddr[31:0]+0];
        idata[15:8] <= i_arr[iaddr[31:0]+1];
        idata[23:16] <= i_arr[iaddr[31:0]+2];
        idata[31:24] <= i_arr[iaddr[31:0]+3];
    end
	

	//32位imem
	/*reg [31:0] i_arr[0:1024*256-1];
	initial begin
		$readmemh("firmware/firmware.hex",i_arr); //firmware/firmware.hex 	dhry.hex
	end
	always @(negedge clk) //posedge clk
    begin
        idata[31:0] <= i_arr[iaddr[31:0]>>2];
    end*/



	//dmem

    reg [7:0] m[0:256*1024-1];	//256*1024-1
    wire [31:0] add0,add1,add2,add3;

    //integer c;
	initial begin
		$readmemh("dhrystone/dhry.hex",m);	//firmware/firmware.hex
		//for(c=0; c<(256*512-1); c=c+1)
		//	m[c] = 0;
	end

    /*assign add0 = (EM_daddr_out & 32'hfffffffc)+ 32'h00000000;
    assign add1 = (EM_daddr_out & 32'hfffffffc)+ 32'h00000001;
    assign add2 = (EM_daddr_out & 32'hfffffffc)+ 32'h00000002;
    assign add3 = (EM_daddr_out & 32'hfffffffc)+ 32'h00000003;*/
	assign add0 = EM_daddr_out + 32'h00000000;
    assign add1 = EM_daddr_out + 32'h00000001;
    assign add2 = EM_daddr_out + 32'h00000002;
    assign add3 = EM_daddr_out + 32'h00000003;
    assign DMEM_drdata_out = {m[add3], m[add2], m[add1], m[add0]};
    always @(posedge clk) begin
		case(EM_daddr_out)
			32'h1000_0000: begin//32'h1000_0000
				$write("%c", dwdata);
				$fflush();
			end
			default:begin
        	if (we[0]) m[add0] <= dwdata[7:0];
        	if (we[1]) m[add1] <= dwdata[15:8];
        	if (we[2]) m[add2] <= dwdata[23:16];
        	if (we[3]) m[add3] <= dwdata[31:24];
			end
       
		endcase
			/*if(we[0] | we[1] | we[2] | we[3])begin
				$write("%c", dwdata);
				$fflush();
			end*/
    	end
		

	 initial begin
		clk = 0;
      reset = 1;
      #10;
      reset = 0;
		repeat (100000000) @(posedge clk);
		$finish;		
	end


	initial begin
		$dumpfile("pipeline_cpu_tb_i.vcd");
		$dumpvars(0, pipeline_cpu_tb_i);
	end

	/*integer i;
	initial begin
	for(i=0; i<5; i=i+1)	//32'h10000  32'h10010
		$display("%d: %h", i, i_arr[i]);
		
	end*/

	integer b;
	initial begin
	//#621550
	for(b=32'hfffffffa; b<32'hffffffff; b=b+1)
		$display("%h: %h", b, m[b]);
	end

	/*integer a;
	initial begin
	#1000
	for(a=32'h10000; a<32'h10010; a=a+1)
		$display("%d: %h", a, dut.rf1.register[a]);
	end*/


endmodule

